<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 10.10.&nbsp; alarm and pause Functions</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch10lev1sec9.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch10lev1sec11.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="ch10lev1sec10"></a>
<h3 class="docSection1Title">10.10. <tt>alarm</tt> and <tt>pause</tt> Functions</h3>
<p class="docText">The <tt>alarm</tt> function allows us to set a timer that will expire at a specified time in the future. When the timer expires, the <tt>SIGALRM</tt> signal is generated. If we ignore or don't catch this signal, its default action is to terminate the process.</P>
<a name="inta04"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><TD class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;unistd.h&gt;

unsigned int alarm(unsigned int <span class="docEmphItalicAlt">seconds</span>);
</pre><BR>

</P></td></TR><TR><TD class="docTableCell" align="right" valign="top"><p class="docText">Returns: 0 or number of seconds until previously set alarm</p></TD></tr></table></P><BR>
<p class="docText">The <span class="docEmphasis">seconds</span> value is the number of clock seconds in the future when the signal should be generated. Be aware that when that time occurs, the signal is generated by the kernel, but there could be additional time before the process gets control to handle the signal, because of processor scheduling delays.</P>
<blockquote>
<p class="docText">Earlier UNIX System implementations warned that the signal could also be sent up to 1 second early. POSIX.1 does not allow this.</p>
</blockquote>
<p class="docText">There is only one of these alarm clocks per process. If, when we call <tt>alarm</tt>, a previously registered alarm clock for the process has not yet expired, the number of seconds left for that alarm clock is returned as the value of this function. That previously registered alarm clock is replaced by the new value.</P>
<p class="docText">If a previously registered alarm clock for the process has not yet expired and if the <span class="docEmphasis">seconds</span> value is 0, the previous alarm clock is canceled. The number of seconds left for that previous alarm clock is still returned as the value of the function.</P>
<p class="docText">Although the default action for <tt>SIGALRM</tt> is to terminate the process, most processes that use an alarm clock catch this signal. If the process then wants to terminate, it can perform whatever cleanup is required before terminating. If we intend to catch <tt>SIGALRM</tt>, we need to be careful to install its signal handler before calling <tt>alarm</tt>. If we call <tt>alarm</tt> first and are sent <tt>SIGALRM</tt> before we can install the signal handler, our process will terminate.</p>
<p class="docText">The <tt>pause</tt> function suspends the calling process until a signal is caught.</P>
<a name="inta176"></a><P><table cellspacing="0" class="allBorders" border="1" RULES="none" cellpadding="5"><colgroup><col width="500"></colgroup><thead></thead><tr><td class="docTableCell" align="left" valign="top"><p class="docText">
<pre>
#include &lt;unistd.h&gt;

int pause(void);
</pre><br>

</p></TD></tr><TR><td class="docTableCell" align="right" valign="top"><p class="docText">Returns: 1 with <tt>errno</tt> set to <tt>EINTR</tt>
</P></td></tr></table></p><br>
<p class="docText">The only time <tt>pause</tt> returns is if a signal handler is executed and that handler returns. In that case, <tt>pause</tt> returns 1 with <tt>errno</tt> set to <tt>EINTR</tt>.</p>
<a name="ch10ex04"></a>
<h5 class="docExampleTitle">Example</h5>
<p class="docText"><a name="idd1e74287"></a><a name="idd1e74290"></a><a name="idd1e74295"></a><a name="idd1e74300"></a><a name="idd1e74305"></a><a name="idd1e74310"></a>Using <tt>alarm</tt> and <tt>pause</tt>, we can put a process to sleep for a specified amount of time. The <tt>sleep1</tt> function in <a class="docLink" href="#ch10fig07">Figure 10.7</a> appears to do this (but it has problems, as we shall see shortly).</p>
<p class="docText">This function looks like the <tt>sleep</tt> function, which we describe in <a class="docLink" href="ch10lev1sec19.html#ch10lev1sec19">Section 10.19</a>, but this simple implementation has three problems.</p>
<div style="font-weight:bold"><ol class="docList" type="1"><li><div style="font-weight:normal"><p class="docList">If the caller already has an alarm set, that alarm is erased by the first call to <tt>alarm</tt>. We can correct this by looking at the return value from the first call to <tt>alarm</tt>. If the number of seconds until some previously set alarm is less than the argument, then we should wait only until the previously set alarm expires. If the previously set alarm will go off after ours, then before returning we should reset this alarm to occur at its designated time in the future.</p></div></li><li><div style="font-weight:normal"><p class="docList">We have modified the disposition for <tt>SIGALRM</tt>. If we're writing a function for others to call, we should save the disposition when we're called and restore it when we're done. We can correct this by saving the return value from <tt>signal</tt> and resetting the disposition before we return.</p></div></li><li><div style="font-weight:normal"><p class="docList">There is a race condition between the first call to <tt>alarm</tt> and the call to <tt>pause</tt>. On a busy system, it's possible for the alarm to go off and the signal handler to be called before we call <tt>pause</tt>. If that happens, the caller is suspended forever in the call to <tt>pause</tt> (assuming that some other signal isn't caught).</p></div></LI></ol></div>
<p class="docText">Earlier implementations of <tt>sleep</tt> looked like our program, with problems 1 and 2 corrected as described. There are two ways to correct problem 3. The first uses <tt>setjmp</tt>, which we show in the next example. The other uses <tt>sigprocmask</tt> and <tt>sigsuspend</tt>, and we describe it in <a class="docLink" href="ch10lev1sec19.html#ch10lev1sec19">Section 10.19</a>.</P>

<a name="ch10fig07"></a>
<h5 class="docExampleTitle">Figure 10.7. Simple, incomplete implementation of <tt>sleep</tt></H5>

<pre>
#include     &lt;signal.h&gt;
#include     &lt;unistd.h&gt;

static void
sig_alrm(int signo)
{
    /* nothing to do, just return to wake up the pause */
}

unsigned int
sleep1(unsigned int nsecs)
{
    if (signal(SIGALRM, sig_alrm) == SIG_ERR)
        return(nsecs);
    alarm(nsecs);       /* start the timer */
    pause();            /* next caught signal wakes us up */
    return(alarm(0));   /* turn off timer, return unslept time */
}
</pre><BR>


<a name="ch10ex05"></a>
<H5 class="docExampleTitle">Example</h5>
<p class="docText"><a name="idd1e74436"></a><a name="idd1e74441"></a><a name="idd1e74446"></a><a name="idd1e74451"></a><a name="idd1e74456"></a><a name="idd1e74461"></a>The SVR2 implementation of <tt>sleep</tt> used <tt>setjmp</tt> and <tt>longjmp</tt> (<a class="docLink" href="ch07lev1sec10.html#ch07lev1sec10">Section 7.10</a>) to avoid the race condition described in problem 3 of the previous example. A simple version of this function, called <tt>sleep2</tt>, is shown in <a class="docLink" href="#ch10fig08">Figure 10.8</a>. (To reduce the size of this example, we don't handle problems 1 and 2 described earlier.)</P>
<p class="docText">The <tt>sleep2</tt> function avoids the race condition from <a class="docLink" href="#ch10fig07">Figure 10.7</a>. Even if the <tt>pause</tt> is never executed, the <tt>sleep2</tt> function returns when the <tt>SIGALRM</tt> occurs.</P>
<p class="docText">There is, however, another subtle problem with the <tt>sleep2</tt> function that involves its interaction with other signals. If the <tt>SIGALRM</tt> interrupts some other signal handler, when we call <tt>longjmp</tt>, we abort the other signal handler. <a class="docLink" href="#ch10fig09">Figure 10.9</a> shows this scenario. The loop in the <tt>SIGINT</tt> handler was written so that it executes for longer than 5 seconds on one of the systems used by the author. We simply want it to execute longer than the argument to <tt>sleep2</tt>. The integer <tt>k</tt> is declared <tt>volatile</tt> to prevent an optimizing compiler from discarding the loop. Executing the program shown in <a class="docLink" href="#ch10fig09">Figure 10.9</a> gives us</P>

<pre>
    $ <span class="docEmphStrong">./a.out</span>
<span class="docEmphStrong">
    ^?</span>                      <span class="docEmphItalicAlt">we type the interrupt character</span>
    sig_int starting
    sleep2 returned: 0
</pre><br>

<p class="docText">We can see that the <tt>longjmp</tt> from the <tt>sleep2</tt> function aborted the other signal handler, <tt>sig_int</tt>, even though it wasn't finished. This is what you'll encounter if you mix the SVR2 <tt>sleep</tt> function with other signal handling. See <a class="docLink" href="ch10lev1sec23.html#ch10qa1q3">Exercise 10.3</a>.</P>

<a name="ch10fig08"></a>
<h5 class="docExampleTitle">Figure 10.8. Another (imperfect) implementation of <tt>sleep</tt></H5>

<pre>
#include   &lt;setjmp.h&gt;
#include   &lt;signal.h&gt;
#include   &lt;unistd.h&gt;

static jmp_buf  env_alrm;

static void
sig_alrm(int signo)
{
    longjmp(env_alrm, 1);
}

unsigned int
sleep2(unsigned int nsecs)
{
    if (signal(SIGALRM, sig_alrm) == SIG_ERR)
        return(nsecs);
    if (setjmp(env_alrm) == 0) {
        alarm(nsecs);       /* start the timer */
        pause();            /* next caught signal wakes us up */
    }
    return(alarm(0));       /* turn off timer, return unslept time */
}
</pre><BR>


<a name="ch10fig09"></a>
<H5 class="docExampleTitle">Figure 10.9. Calling <tt>sleep2</tt> from a program that catches other signals</h5>

<pre>
#include "apue.h"

unsigned int        sleep2(unsigned int);
static void         sig_int(int);

int
main(void)
{
    unsigned int        unslept;

    if (signal(SIGINT, sig_int) == SIG_ERR)
        err_sys("signal(SIGINT) error");
    unslept = sleep2(5);
    printf("sleep2 returned: %u\n", unslept);
    exit(0);
}

static void
sig_int(int signo)
{
    int            i, j;
    volatile int   k;

    /*
     * Tune these loops to run for more than 5 seconds
     * on whatever system this test program is run.
     */
    printf("\nsig_int starting\n");
    for (i = 0; i &lt; 300000; i++)
        for (j = 0; j &lt; 4000; j++)
            k += i * j;
    printf("sig_int finished\n");
}
</pre><BR>


<p class="docText"><a name="idd1e74625"></a>The purpose of these two examples, the <tt>sleep1</tt> and <tt>sleep2</tt> functions, is to show the pitfalls in dealing naively with signals. The following sections will show ways around all these problems, so we can handle signals reliably, without interfering with other pieces of code.</P>
<a name="ch10ex06"></a>
<h5 class="docExampleTitle">Example</H5>
<p class="docText">A common use for <tt>alarm</tt>, in addition to implementing the <tt>sleep</tt> function, is to put an upper time limit on operations that can block. For example, if we have a <tt>read</tt> operation on a device that can block (a &quot;slow&quot; device, as described in <a class="docLink" href="ch10lev1sec5.html#ch10lev1sec5">Section 10.5</a>), we might want the <tt>read</tt> to time out after some amount of time. The program in <a class="docLink" href="#ch10fig10">Figure 10.10</a> does this, reading one line from standard input and writing it to standard output.</P>
<p class="docText"><a name="idd1e74667"></a><a name="idd1e74670"></a><a name="idd1e74675"></a><a name="idd1e74678"></a><a name="idd1e74683"></a><a name="idd1e74686"></a><a name="idd1e74691"></a><a name="idd1e74696"></a><a name="idd1e74701"></a>This sequence of code is common in UNIX applications, but this program has two problems.</p>
<div style="font-weight:bold"><ol class="docList" type="1"><li><div style="font-weight:normal"><p class="docList">The program in <a class="docLink" href="#ch10fig10">Figure 10.10</a> has one of the same flaws that we described in <a class="docLink" href="#ch10fig07">Figure 10.7</a>: a race condition between the first call to <tt>alarm</tt> and the call to <tt>read</tt>. If the kernel blocks the process between these two function calls for longer than the alarm period, the <tt>read</tt> could block forever. Most operations of this type use a long alarm period, such as a minute or more, making this unlikely; nevertheless, it is a race condition.</p></div></li><LI><div style="font-weight:normal"><p class="docList">If system calls are automatically restarted, the <tt>read</tt> is not interrupted when the <tt>SIGALRM</tt> signal handler returns. In this case, the timeout does nothing.</p></div></LI></ol></div>
<p class="docText">Here, we specifically want a slow system call to be interrupted. POSIX.1 does not give us a portable way to do this; however, the XSI extension in the Single UNIX Specification does. We'll discuss this more in <a class="docLink" href="ch10lev1sec14.html#ch10lev1sec14">Section 10.14</a>.</p>

<a name="ch10fig10"></a>
<H5 class="docExampleTitle">Figure 10.10. Calling <tt>read</tt> with a timeout</h5>

<pre>
#include "apue.h"

static void sig_alrm(int);

int
main(void)
{
    int     n;
    char    line[MAXLINE];

    if (signal(SIGALRM, sig_alrm) == SIG_ERR)
        err_sys("signal(SIGALRM) error");

    alarm(10);
    if ((n = read(STDIN_FILENO, line, MAXLINE)) &lt; 0)
        err_sys("read error");
    alarm(0);

    write(STDOUT_FILENO, line, n);
    exit(0);
}

static void
sig_alrm(int signo)
{
    /* nothing to do, just return to interrupt the read */
}
</pre><br>


<a name="ch10ex07"></a>
<h5 class="docExampleTitle">Example</h5>
<p class="docText">Let's redo the preceding example using <tt>longjmp</tt>. This way, we don't need to worry about whether a slow system call is interrupted.</p>
<p class="docText"><a name="idd1e74790"></a><a name="idd1e74795"></a><a name="idd1e74800"></a><a name="idd1e74805"></a><a name="idd1e74810"></a><a name="idd1e74815"></a><a name="idd1e74818"></a>This version works as expected, regardless of whether the system restarts interrupted system calls. Realize, however, that we still have the problem of interactions with other signal handlers, as in <a class="docLink" href="#ch10fig08">Figure 10.8</a>.</p>

<a name="ch10fig11"></a>
<h5 class="docExampleTitle">Figure 10.11. Calling <tt>read</tt> with a timeout, using <tt>longjmp</tt></h5>

<pre>
#include "apue.h"
#include &lt;setjmp.h&gt;

static void       sig_alrm(int);
static jmp_buf    env_alrm;

int
main(void)
{
    int     n;
    char    line[MAXLINE];

    if (signal(SIGALRM, sig_alrm) == SIG_ERR)
        err_sys("signal(SIGALRM) error");
    if (setjmp(env_alrm) != 0)
        err_quit("read timeout");

    alarm(10);
    if ((n = read(STDIN_FILENO, line, MAXLINE)) &lt; 0)
        err_sys("read error");
    alarm(0);

    write(STDOUT_FILENO, line, n);
    exit(0);
}

static void
sig_alrm(int signo)
{
    longjmp(env_alrm, 1);
}
</pre><br>


<p class="docText">If we want to set a time limit on an I/O operation, we need to use <tt>longjmp</tt>, as shown previously, realizing its possible interaction with other signal handlers. Another option is to use the <tt>select</tt> or <tt>poll</tt> functions, described in <a class="docLink" href="ch14lev1sec5.html#ch14lev2sec14">Sections 14.5.1</a> and <a class="docLink" href="ch14lev1sec5.html#ch14lev2sec15">14.5.2</a>.</p>

<a href="17021535.html"><img src="images/pixel.gif" alt="" width="1" height="1" border="0"></a><ul></ul></td></tr></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=ch10lev1sec9.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=ch10lev1sec11.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--138-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--138-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
